

import cv2
import numpy as np
import subprocess
import io
from PIL import Image
import operation

from typing import List, Tuple

def fast_screenshot(region=None, device_serial=None):
    """快速截取屏幕"""
    cmd = "adb exec-out screencap -p"
    if device_serial:
        cmd = f"adb -s {device_serial} exec-out screencap -p"

    result = subprocess.run(cmd,
                            shell=True,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)

    if result.returncode != 0:
        raise RuntimeError(f"截图失败: {result.stderr.decode('utf-8')}")

    img = Image.open(io.BytesIO(result.stdout))
    if region:
        x, y, width, height = region
        img = img.crop((x, y, x + width, y + height))
    return img


def find_image_on_screen_adb(target_image_path, confidence=0.90, region=None, show_result=False, device_serial=None):
    """在屏幕上查找目标图片"""
    try:

        # 1. 快速截图
        screen_img = fast_screenshot(region, device_serial=device_serial)
        # 将屏幕截图转换为灰度图像
        screen_gray = cv2.cvtColor(np.array(screen_img), cv2.COLOR_RGB2GRAY)
        screen_cv = cv2.cvtColor(np.array(screen_img), cv2.COLOR_RGB2BGR)
        # screen_gray = cv2.cvtColor(screen_cv, cv2.COLOR_BGR2GRAY)

        # 2. 读取目标图像
        # 读取目标图像和屏幕截图
        target_image = cv2.imdecode(np.fromfile(target_image_path, dtype=np.uint8), cv2.IMREAD_GRAYSCALE)
        # target_image = cv2.imread(target_image_path, cv2.IMREAD_GRAYSCALE)
        if target_image is None:
            raise ValueError(f"无法加载目标图像: {target_image_path}")

        # 3. 模板匹配
        res = cv2.matchTemplate(screen_gray, target_image, cv2.TM_CCOEFF_NORMED)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

        if max_val >= confidence:
            target_center = (max_loc[0] + target_image.shape[1] // 2,
                             max_loc[1] + target_image.shape[0] // 2)

            if region:
                target_center = (target_center[0] + region[0],
                                 target_center[1] + region[1])

            if show_result:
                h, w = target_image.shape
                top_left = max_loc
                bottom_right = (top_left[0] + w, top_left[1] + h)
                cv2.rectangle(screen_cv, top_left, bottom_right, (0, 255, 0), 2)
                cv2.putText(screen_cv, f"Confidence: {max_val:.2f}",
                            (top_left[0], top_left[1] - 10),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
                cv2.imshow("Match Result", screen_cv)
                cv2.waitKey(3000)  # 显示3秒
                cv2.destroyAllWindows()

            return target_center
        return False

    except Exception as e:
        print(f"查找图像出错: {str(e)}")
        return False


def find_image_on_screen_adb_not_shot(img, target_image_path, confidence=0.90, region=None, show_result=False):
    """在屏幕上查找目标图片"""
    try:
        # 1. 快速截图
        screen_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
        screen_gray = cv2.cvtColor(screen_cv, cv2.COLOR_BGR2GRAY)

        # 2. 读取目标图像
        target_image = cv2.imread(target_image_path, cv2.IMREAD_GRAYSCALE)
        if target_image is None:
            raise ValueError(f"无法加载目标图像: {target_image_path}")

        # 3. 模板匹配
        res = cv2.matchTemplate(screen_gray, target_image, cv2.TM_CCOEFF_NORMED)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

        if max_val >= confidence:
            target_center = (max_loc[0] + target_image.shape[1] // 2,
                             max_loc[1] + target_image.shape[0] // 2)

            if region:
                target_center = (target_center[0] + region[0],
                                 target_center[1] + region[1])

            if show_result:
                h, w = target_image.shape
                top_left = max_loc
                bottom_right = (top_left[0] + w, top_left[1] + h)
                cv2.rectangle(screen_cv, top_left, bottom_right, (0, 255, 0), 2)
                cv2.putText(screen_cv, f"Confidence: {max_val:.2f}",
                            (top_left[0], top_left[1] - 10),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
                cv2.imshow("Match Result", screen_cv)
                cv2.waitKey(3000)  # 显示3秒
                cv2.destroyAllWindows()

            return target_center
        return False

    except Exception as e:
        print(f"查找图像出错: {str(e)}")
        return False




def find_all_image_on_screen_adb(target_image_path: str,
                                 confidence: float = 0.90,
                                 region: Tuple[int, int, int, int] = None,
                                 show_result: bool = False,
                                 device_serial: str = None,
                                 min_distance: int = 5) -> List[Tuple[int, int]]:
    """
    在屏幕上查找目标图片（返回去重后的中心点坐标）

    Args:
        target_image_path: 目标图片路径
        confidence: 匹配阈值 (0-1)
        region: 查找区域 (x, y, width, height)
        show_result: 是否显示匹配结果
        device_serial: ADB设备序列号
        min_distance: 最小去重像素距离（小于此距离视为重复）

    Returns:
        list: 去重后的中心点坐标 [(x1,y1), (x2,y2), ...]
    """
    try:
        # 1. 获取截图
        screen_img = fast_screenshot(region, device_serial)
        screen_cv = cv2.cvtColor(np.array(screen_img), cv2.COLOR_RGB2BGR)
        screen_gray = cv2.cvtColor(screen_cv, cv2.COLOR_BGR2GRAY)

        # 2. 加载目标图像
        target_image = cv2.imread(target_image_path, cv2.IMREAD_GRAYSCALE)
        if target_image is None:
            raise ValueError(f"无法加载目标图像: {target_image_path}")
        h, w = target_image.shape

        # 3. 模板匹配
        res = cv2.matchTemplate(screen_gray, target_image, cv2.TM_CCOEFF_NORMED)

        # 4. 获取所有匹配位置（使用非极大值抑制）
        loc = np.where(res >= confidence)
        centers = []
        for pt in zip(*loc[::-1]):
            centers.append((pt[0] + w // 2, pt[1] + h // 2))

        # 5. 坐标去重（基于min_distance）
        if len(centers) > 1:
            centers = _remove_close_points(centers, min_distance)

        # 6. 转换为全局坐标
        if region:
            x_offset, y_offset = region[0], region[1]
            centers = [(x + x_offset, y + y_offset) for x, y in centers]

        # 7. 可视化（可选）
        if show_result and centers:
            _draw_match_results(screen_cv, centers, w, h)

        return centers

    except Exception as e:
        print(f"图像查找错误: {str(e)}")
        return []


def _remove_close_points(points: List[Tuple[int, int]],
                         min_distance: int) -> List[Tuple[int, int]]:
    """基于距离的去重函数"""
    unique_points = []
    for pt in points:
        keep = True
        for kept in unique_points:
            if ((pt[0] - kept[0]) ** 2 + (pt[1] - kept[1]) ** 2) <= min_distance ** 2:
                keep = False
                break
        if keep:
            unique_points.append(pt)
    return unique_points


def _draw_match_results(image, centers, w, h):
    """绘制匹配结果"""
    for (x, y) in centers:
        cv2.rectangle(image,
                      (int(x - w // 2), int(y - h // 2)),
                      (int(x + w // 2), int(y + h // 2)),
                      (0, 255, 0), 2)
    cv2.imshow("Match Results", image)
    cv2.waitKey(3000)
    cv2.destroyAllWindows()




if __name__ == "__main__":

    client = operation.connect_emulator()
    devices = client.devices()

    if not devices:
        print("没有找到连接的设备")
        exit()

    # 打印所有设备信息
    print("可用设备:")
    for i, device in enumerate(devices):
        print(f"{i}: {device.serial}")

    if not devices:
        print("没有找到连接的设备")
        exit()

    # 打印所有设备信息
    print("可用设备:")
    for i, device in enumerate(devices):
        print(f"{i}: {device.serial}")

    # 自动选择第一个设备（或让用户选择）
    selected_device = devices[1]
    print(f"\n选择设备: {selected_device.serial}")
    img = r"E:\DESKTOP\img\use_items\gold-ingot.bmp"
    res  = find_all_image_on_screen_adb(img,device_serial=selected_device.serial, confidence=0.9, show_result=True)
    print(len(res))